/*
Copyright (C) 2015 Jochem Raat

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <renderedMap.h>

using namespace sf;

RenderedMapGenerator::RenderedMapGenerator()
{
    float sunStrength = 0.6;

    Light sun;
    sun.color = {1.0f * sunStrength, 1.0f * sunStrength,
                 0.6f * sunStrength};
    sun.falloff = {0.0f, 0.0f, 0.0f};
    sun.position = {-1.0f * pow(10.0f, 3.0f), -1.0f * pow(10.0f, 3.0f),
                    1 * pow(10.0f, 4.0f)};

    lights.push_back(sun);

    float atmosphereStrength = 0.4f;
    diffuse = {0.8f * atmosphereStrength,
               0.8f * atmosphereStrength,
               1.0f * atmosphereStrength};

    lightingGenerator = new LightingGenerator();
}

Image RenderedMapGenerator::generateRenderedMap(double *heightmap,
                                                double *surfaceHeightmap,
                                                Biome *biomeMap,
                                                Image biomeImage)
{
    Vector2u size = biomeImage.getSize();
    lightingGenerator->generateNormalMap(surfaceHeightmap,
                                        size.x, size.y, false);
    lightingGenerator->generateLightMap(lights, diffuse);

    Image renderedImage;
    renderedImage.create(size.x, size.y);

    Vec3f *lightmap = lightingGenerator->lightmap;
    for (unsigned x = 0; x < size.x; x++)
        for (unsigned y = 0; y < size.y; y++) {
            Color mapColor = biomeImage.getPixel(x, y);
            int index = x + y * size.x;

            if (biomeMap[index] == OCEAN || biomeMap[index] == LAKE)
                mapColor = renderWaterPixel(heightmap[index],
                                            surfaceHeightmap[index],
                                            biomeImage.getPixel(x,y));


            mapColor.r = std::min(255, (int) (((float) mapColor.r) *
                                              lightmap[index].x));
            mapColor.g = std::min(255, (int) (((float) mapColor.g) *
                                              lightmap[index].y));
            mapColor.b = std::min(255, (int) (((float) mapColor.b) *
                                              lightmap[index].z));
            renderedImage.setPixel(x, y, mapColor);
        }

    return renderedImage;
}

Color RenderedMapGenerator::renderWaterPixel(double height,
                                             double waterLevel,
                                             Color biomeColor)
{
    return getLinearInterpolate(
        getLinearInterpolate
        (biomeColor, deepVersion(biomeColor),
         ((double) ((int) (height * 10.0) / waterLevel)) / 10.0),
        getLinearInterpolate
        (biomeColor, deepVersion(biomeColor),  height / waterLevel),
        0.3);
}

Color RenderedMapGenerator::deepVersion(Color c)
{
    float multiplier = 0.2;
    return Color(c.r * multiplier, c.g * multiplier,
                 c.b * multiplier, c.a);
}

Color RenderedMapGenerator::getLinearInterpolate(Color c1,
                                                 Color c2,
                                                 double weight)
{
    return Color(c1.r * weight + c2.r * (1.0 - weight),
                 c1.g * weight + c2.g * (1.0 - weight),
                 c1.b * weight + c2.b * (1.0 - weight),
                 c1.a * weight + c2.a * (1.0 - weight));
}
